from pathlib import Path
from typing import List
from uuid import UUID

from fastapi import UploadFile
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from crud.tender_crud import TenderCRUD
from crud.tender_document_crud import TenderDocumentCRUD
from .file_manager import FileManager


class TenderFile(BaseModel):
    name: str
    file_path: str


class TenderInfo(BaseModel):
    id: str
    category: str
    quarter: str


class TenderService:
    def __init__(self, db: AsyncSession):
        self.tender_crud = TenderCRUD(db)
        self.tender_document_crud = TenderDocumentCRUD(db)

    async def create_tender(
        self, category: str, quarter: str, document: UploadFile
    ) -> UUID:
        manager = FileManager(category, quarter)
        file_path = await manager.create_tender_document_file(document)
        original_filename = Path(document.filename).stem

        tender = await self.tender_crud.create(category, quarter)
        tender_document_id = await self.tender_document_crud.create(
            original_name=original_filename,
            file_path=str(file_path),
            tendering_id=tender.id,
        )
        return tender.id

    async def list_tenders(self) -> List[TenderInfo]:
        tenders = await self.tender_crud.get_all()
        tender_info_list = [
            TenderInfo(
                id=str(tender.id), category=tender.category, quarter=tender.quarter
            )
            for tender in tenders
        ]
        return tender_info_list

    async def get_tender_document(self, tender_id: UUID) -> TenderFile | None:
        tender_document = await self.tender_document_crud.get_by_tender_id(tender_id)
        if not tender_document:
            return None
        return TenderFile(
            name=tender_document.original_name, file_path=tender_document.file_path
        )

    async def delete_tender(self, tender_id: UUID) -> bool:
        tender = await self.tender_crud.get_by_id(tender_id)
        manager = FileManager(tender.category, tender.quarter)
        manager.delete_all()
        await self.tender_crud.delete(tender_id)
        return True
